#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/5/20 15:15
# @Author  : Grayson Liu
# @Email   : graysonliu@foxmail.com
# @File    : tdm.py.py
import sqlite3

import pandas as pd
import numpy as np
from dw.dw import DwUtil
import os
import tdm.rule as rule


class TdmUtil:
    """
    标签数据层的工具类
    """
    name_list = ["cpu2006_fprate", "cpu2006_fpspeed", "cpu2006_intrate", "cpu2006_intspeed",
                 "cpu2017_fprate", "cpu2017_fpspeed", "cpu2017_intrate", "cpu2017_intspeed",
                 "jbb2015_comp", "jbb2015_dist", "jbb2015_multi",
                 "jvm2008", "power_ssj2008"]
    # 适用于rate（吞吐量）规则的分数名称
    rate_list = ["cpu2006_fprate", "cpu2006_intrate", "cpu2017_fprate", "cpu2017_intrate",
                 "jbb2015_comp", "jbb2015_dist", "jbb2015_multi", "jvm2008", "power_ssj2008"]

    # def __init__(self, dw: DwUtil, tdm_folder_path: str = "../data/tdm"):
    def __init__(self, dw: DwUtil, tdm_folder_path: str = "data/tdm"):

        """

        :param dw:
        :param tdm_folder_path:
        """
        self.tdm_folder_path = tdm_folder_path
        self.dw = dw

    def get_processor_score(self, save_to_csv: bool = False, import_to_db: bool = False) -> pd.DataFrame:
        """
        获得标签数据层的表格，可以导出为CSV文件或导入数据库
        :param save_to_csv: 是否导出为CSV文件
        :param import_to_db: 是否导入数据库
        :return:
        """
        # 1. 从cpu2017相关数据仓库中获得常见处理器型号
        processor_score_df = self.dw.execute_sql("""
        SELECT DISTINCT processor FROM dw_cpu2017_fprate
        UNION
        SELECT DISTINCT processor FROM dw_cpu2017_fpspeed
        UNION
        SELECT DISTINCT processor FROM dw_cpu2017_intspeed
        UNION
        SELECT DISTINCT processor FROM dw_cpu2017_intrate
        """)

        def get_statics(name: str):
            """
            私有方法，用于获得各benchmark分数相关统计信息的函数，数据来源于数据仓库的CSV文件
            其中rate相关数据，分数是相应地除以每一条记录的核数，来进行统计的
            :param name: benchmark名称（数据仓库的），例如cpu2017_intspeed等
            :return: 返回均值和标准差
            """
            if name in ["cpu2006_fprate", "cpu2006_intrate", "cpu2017_fprate", "cpu2017_intrate", "jbb2015_comp",
                        "jbb2015_dist", "jbb2015_multi", "jvm2008", "power_ssj2008"]:
                # 是rate的情况，需要额外处理
                # data = pd.read_csv(os.path.join("../data/dw", f"dw_{name}.csv"), index_col=0)
                data = pd.read_csv(os.path.join("data/dw", f"dw_{name}.csv"), index_col=0)
                data = data.drop(data[data["result"] == 0.0].index)  # 删除分数为0的行
                data["core_result"] = data["result"] / data["num_core"]
                return data["core_result"].mean(), data["core_result"].std()
            else:
                # data = pd.read_csv(os.path.join("../data/dw", f"dw_{name}.csv"), index_col=0)
                data = pd.read_csv(os.path.join("data/dw", f"dw_{name}.csv"), index_col=0)
                data = data.drop(data[data["result"] == 0.0].index)  # 删除分数为0的行
                return data["result"].mean(), data["result"].std()

        # 2. 获得13种benchmark相关分数的统计信息
        statics_dict = {}
        for name in self.name_list:
            statics_dict[name] = get_statics(name)

        # 3. 根据编写完成的规则，对每一个处理器生成benchmark得分
        for name in self.name_list:
            if name in self.rate_list:
                # 应用rate规则
                processor_score_df[name] = processor_score_df.apply(
                    lambda row: rule.rate_rule(row["processor"],
                                               statics_dict[name][0],
                                               statics_dict[name][1],
                                               self.dw,
                                               name), axis=1)
            else:
                # 应用speed规则
                processor_score_df[name] = processor_score_df.apply(
                    lambda row: rule.speed_rule(row["processor"],
                                                statics_dict[name][0],
                                                statics_dict[name][1],
                                                self.dw,
                                                name), axis=1)

        # 4. 根据benchmark的得分，根据转换逻辑生成6项子等级评分
        processor_score_df["int_grade"] = processor_score_df.apply(rule.int_grade_rule, axis=1)
        processor_score_df["float_grade"] = processor_score_df.apply(rule.float_grade_rule, axis=1)
        processor_score_df["single_grade"] = processor_score_df.apply(rule.single_grade_rule, axis=1)
        processor_score_df["multi_grade"] = processor_score_df.apply(rule.multi_grade_rule, axis=1)
        processor_score_df["java_grade"] = processor_score_df.apply(rule.java_grade_rule, axis=1)
        processor_score_df["power_grade"] = processor_score_df.apply(rule.power_grade_rule, axis=1)
        processor_score_df["overall_grade"] = processor_score_df.apply(rule.overall_grade_rule, axis=1)

        # 5. 最后处理一下DataFrame以便后续导入
        processor_score_df.index.name = "id"
        processor_score_df.index = processor_score_df.index + 1

        if save_to_csv:
            processor_score_df.to_csv(os.path.join(self.tdm_folder_path, "processor_result.csv"))

        if import_to_db:
            conn = sqlite3.connect(self.dw.db_path)
            c = conn.cursor()
            # with open("../tdm/create_tdm_template", "r", True, 'UTF-8') as f:
            with open("tdm/create_tdm_template", "r", True, 'UTF-8') as f:
                sql = f.read()
                c.executescript(sql)
            processor_score_df.to_sql("processor_result", conn, if_exists="append")
            conn.commit()
            c.close()
            conn.close()

        return processor_score_df
